#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/select.h>
#include "shmem.h"
#include "msg_queue_peer.h"
#include <pthread.h>

#define N 102400
char buf[N] = {};
union val_t
{
    BOOL b_val;  // bool类型存储空间
    int i_val;   // 整形值存储空间
    float f_val; // 浮点值存储空间
};

struct control
{
    long Equ;        // 消息类型
    int key;         // 设备ID
    char name[32];   // 设备名称
    union val_t val; // 数据设置
    int addr;        // 线圈寄存器
    int type;        // 数据点值的类型，1：bool类型 2：int型  3：float型
};
// 消息队列

typedef struct data32
{
    int key;
    char name[32];
    union val_t val; // 实时数据
    int type;        // 数据类型
} data32_data;
struct datam
{
    int key;
    char name[32];
    union val_t val; // 实时数据
    int addr;        // modbus地址
    int type;        // 数据类型
};

typedef struct data
{
    struct data32 d32[10];
    struct datam dmod[10]; // Modbus结构体数组
    int arrsize;
} shmdata;
// 共享内存

struct node
{
    uint32_t hw;   // 红外
    uint32_t led;  // 灯
    uint32_t fire; // 防火
    float bat;     // 电量
    float t;       // 温度
    float h;       // 湿度
    uint32_t feng; // 风扇
    uint32_t bee;  // 蜂鸣器
};
struct node n;
int acceptfd;
void *handler_msgrc() // 消息队列获取信息
{
    while (1)
    {
        struct control ctrl;
        // 创建消息队列
        if (msg_queue_recv("msg", &ctrl, sizeof(ctrl), 32, 0) < 0)
        {
            perror("msg create erro\n");
            return NULL;
        }
      
        switch (ctrl.key)
        {
        case 305:
            if (ctrl.val.i_val == 1)
            {
                ssize_t send_ret = send(acceptfd, "RED_ON", strlen("RED_ON") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending RED_ON message");
                }
                else
                {
                }
            }
            else if (ctrl.val.i_val == 0)
            {
                ssize_t send_ret = send(acceptfd, "RED_OFF", strlen("RED_OFF") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending RED_OFF message");
                }
                else
                {
                }
            }
            break;
        case 306:
            if (ctrl.val.i_val == 1)
            {
                ssize_t send_ret = send(acceptfd, "LED_ON", strlen("LED_ON") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending LED_ON message");
                }
                else
                {
                }
            }
            else if (ctrl.val.i_val == 0)
            {
                ssize_t send_ret = send(acceptfd, "LED_OFF", strlen("LED_OFF") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending LED_OFF message");
                }
                else
                {
                }
            }
            break;
        case 307:
            if (ctrl.val.i_val == 1)
            { printf("123\n");
                ssize_t send_ret = send(acceptfd, "BEEP_ON", strlen("BEEP_ON") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending BEEP_ON message");
                }
                else
                {
                }
            }
            else if (ctrl.val.i_val == 0)
            {
                ssize_t send_ret = send(acceptfd, "BEEP_OFF", strlen("BEEP_OFF") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending BEEP_OFF message");
                }
                else
                {
                }
            }
            break;
        case 308:
            if (ctrl.val.i_val == 1)
            {
                printf("aaa\n");
                ssize_t send_ret = send(acceptfd, "FENG_ON", strlen("FENG_ON") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending FENG_ON message");
                }
                else
                {
                }
            }
            else if (ctrl.val.i_val == 0)
            {
                ssize_t send_ret = send(acceptfd, "FENG_OFF", strlen("FENG_OFF") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending FENG_OFF message");
                }
                else
                {
                }
            }
            break;
        case 309:
            if (ctrl.val.i_val == 1)
            {
                ssize_t send_ret = send(acceptfd, "FIRE_ON", strlen("FIRE_ON") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending FIRE_ON message");
                }
                else
                {
                }
            }
            else if (ctrl.val.i_val == 0)
            {
                ssize_t send_ret = send(acceptfd, "FIRE_OFF", strlen("FIRE_OFF") + 1, 0);
                if (send_ret < 0)
                {
                    // 发送出错，进行错误处理，这里简单打印错误信息，实际可根据需求完善
                    perror("Error sending FIRE_OFF message");
                }
                else
                {
                }
            }
            break;

        default:
            break;
        }
        sleep(1);
    }
}

int main(int argc, char const *argv[])
{

    if (argc != 2)
    {
        printf("usage:<port>\n");
        return -1;
    }
    // 1.创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    printf("sockfd:%d\n", sockfd);
    // 2.bind绑定ip和port
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = INADDR_ANY;

    socklen_t addrlen = sizeof(saddr);
    if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
    {
        perror("bind erro\n");
        return -1;
    }
    printf("bind ok\n");
    // 3.监听 listen将主动套接字变为被动套接字
    if (listen(sockfd, 6) < 0)
    {
        perror("listen err");
        return -1;
    }
    printf("listen ok\n");

    struct shm_param para;
    // 初始化共享内存
    if (shm_init(&para, "shm", sizeof(shmdata)) < 0)
    {
        perror("shm create erro\n");
        return -1;
    }
    shmdata *shmdata = (struct data *)shm_getaddr(&para);
    pthread_t tid;
    while (1)
    {
        // 4.accept阻塞等待连接可以建立，有的话就解除阻塞建立连接，并产生一个新的套接字
        acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &addrlen);
        if (acceptfd < 0)
        {
            printf("acceptfd erro");
            return -1;
        }
        printf("acceptfd ok\n");
        printf("acceptfd:%d \n", acceptfd);
        
        if (pthread_create(&tid, NULL, handler_msgrc, NULL) != 0)
        {
            perror("create err");
            return -1;
        }
        
        while (1)
        {
            int ret = recv(acceptfd, buf, sizeof(buf), 0);
            if (ret < 0)
            {
                perror("recv err");
                return -1;
            }
            else if (ret == 0)
            {
                printf("%s out\n", inet_ntoa(caddr.sin_addr));
                close(acceptfd);
                break;
            }
            else
            {


               // printf("%s\n",buf);
                sscanf(buf, "%f %f %f %u %u %u %u %u",
                       &n.bat, &n.t, &n.h,
                       &n.hw, &n.led, &n.bee,
                       &n.feng, &n.fire);

                // printf("Parsed successfully:\n");
                printf("红外感应: %u\n灯光: %u\n防火警告: %u\n", n.hw, n.led, n.fire);
                printf("蜂鸣器: %.2f\n温度: %.2f\n湿度: %.2f\n", n.bat, n.t, n.h);
                printf("风扇: %u\n蜂鸣器: %u\n", n.feng, n.bee);
                printf("-------------------------------------------\n");
                shmdata->d32[0].val.f_val = 0;
                
                shmdata->d32[1].val.f_val = n.bat;
                shmdata->d32[2].val.f_val = n.t;
                shmdata->d32[3].val.f_val = n.h;
                shmdata->d32[4].val.b_val = n.hw;
                shmdata->d32[5].val.b_val = n.led;
                shmdata->d32[6].val.b_val = n.bee;
                shmdata->d32[7].val.b_val = n.feng;
                shmdata->d32[8].val.b_val = n.fire;
                sleep(1);
            }
        }
    }
    pthread_detach(tid);
    close(sockfd);
    return 0;
}
